package erp

import (
	"context"
	"encoding/json"
	"strconv"
	"strings"

	"mall/common/moneyx"
	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/logic/backend/util"
	orderUtil "mall/service/backend/api/internal/logic/order/util"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/common/erp"
	"mall/service/order/rpc/orderclient"

	// "github.com/sirupsen/logrus"
	"github.com/friendsofgo/errors"
	"github.com/zeromicro/go-zero/core/logx"
)

type PushOrderToErpLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 推送订单到erp
func NewPushOrderToErpLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PushOrderToErpLogic {
	return &PushOrderToErpLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *PushOrderToErpLogic) PushOrderToErp(req *types.PushOrderToErpReq) (*types.BaseMsgResp, error) {
	if req.Ids != nil && len(*req.Ids) > 0 {
		queryMaps, err := l.getOrderMap(req.Ids)
		if err != nil {
			return nil, err
		}
		// 文档地址：https://open.hupun.com/api-doc/erp/b2c/trades/open
		if err = l.pushOrderToErp(queryMaps); err != nil {
			return nil, err
		}
	}

	return &types.BaseMsgResp{
		Success: true,
		Msg:     "推送订单至ERP成功", //订单推送
		// Msg:     l.svcCtx.Trans.Trans(l.ctx, res.Msg),
	}, nil
}

func (l *PushOrderToErpLogic) getOrderMap(ids *string) (map[string]string, error) {
	data, err := l.svcCtx.OrderRpc.BackendGetOrderList(l.ctx, &orderclient.BackendOrderListReq{
		Ids:           ids,
		WithSkus:      pointy.GetPointer(uint32(1)),
		WithAddresses: pointy.GetPointer(uint32(1)),
		WithPayments:  pointy.GetPointer(uint32(1)),
	})
	if err != nil {
		logx.Errorw("PushOrderToErp getOrderMap OrderRpc.BackendGetOrderList err", logx.Field("detail", err.Error()))
		return nil, err
	}
	// logx.Infof("PushOrderToErp getOrderMap: %+v ", data)
	if len(data.List) > 0 {
		var trades []map[string]any
		for _, v := range data.List {
			if v.Id == nil || *v.Id == 0 {
				continue
			}

			var updatedAt string
			var orderItems []map[string]any
			var detailedAddress string
			var consignee string
			var orderSn string
			var buyer string
			var remark string
			var mobile string
			var discountAmount string
			var endedAt string
			var hasOrderRefund uint64
			var payNo string
			var paidAt string
			var payType string
			var amount string
			var freight string
			var actualAmount string
			var orderTypeText string
			var district string
			var city string
			var province string
			var postalCode string
			var sellerMemo string
			var shippedAt string
			var status uint32
			if v.Remark != nil && len(*v.Remark) > 0 {
				remark = *v.Remark
			}
			if v.SellerMemo != nil && len(*v.SellerMemo) > 0 {
				sellerMemo = *v.SellerMemo
			}
			if v.ActualAmount != nil && len(*v.ActualAmount) > 0 {
				actualAmount = *v.ActualAmount
			}
			if v.DiscountAmount != nil && len(*v.DiscountAmount) > 0 {
				discountAmount = *v.DiscountAmount
			}
			if v.PaidAt != nil && len(*v.PaidAt) > 0 {
				paidAt = *v.PaidAt
			}
			if v.ShippedAt != nil && len(*v.ShippedAt) > 0 {
				shippedAt = *v.ShippedAt
			}
			if v.UpdatedAt != nil {
				updatedAt = *v.UpdatedAt
			}
			if v.Buyer != nil && len(*v.Buyer) > 0 {
				buyer = *v.Buyer
			}
			if v.ClosedAt != nil {
				endedAt = *v.ClosedAt
			}
			if (v.RefundAmount != nil && len(*v.RefundAmount) > 0 && *v.RefundAmount != "0") || len(v.Refunds) > 0 {
				hasOrderRefund = 1
			}
			if v.Freight != nil && len(*v.Freight) > 0 {
				freight = *v.Freight
			}
			if v.Sn != nil && len(*v.Sn) > 0 {
				orderSn = *v.Sn
			}
			if v.OrderType != nil {
				if orderType := orderUtil.GetOrderTypeText(v.OrderType); orderType != nil {
					orderTypeText = *orderType
				}
			}
			if v.TradeState != nil {
				status = util.OrderStatusToErpOrderStatus(v.TradeState)
			}
			if len(v.Addresses) > 0 {
				address := v.Addresses[0]
				if address != nil {
					if address.Mobile != nil && len(*address.Mobile) > 0 {
						mobile = *address.Mobile
					}
					if address.Province != nil && len(*address.Province) > 0 {
						province = *address.Province
					}
					if address.City != nil && len(*address.City) > 0 {
						city = *address.City
					}
					if address.District != nil && len(*address.District) > 0 {
						district = *address.District
					}
					if address.Address != nil && len(*address.Address) > 0 {
						detailedAddress = *address.Address
					}
					if address.PostalCode != nil && len(*address.PostalCode) > 0 {
						postalCode = *address.PostalCode
					}
					if address.Consignee != nil && len(*address.Consignee) > 0 {
						consignee = *address.Consignee
					}
				}
			}
			if len(v.Payments) > 0 {
				payment := v.Payments[0]
				if payment != nil {
					if payment.No != nil && len(strings.TrimSpace(*payment.No)) > 0 {
						payNo = *payment.No
					}
					if payment.Amount != nil && len(strings.TrimSpace(*payment.Amount)) > 0 {
						amount = *payment.Amount
					}
					if payment.Name != nil && len(strings.TrimSpace(*payment.Name)) > 0 {
						payType = *payment.Name
					}
				}
			}
			if len(v.Skus) > 0 {
				for _, sku := range v.Skus {
					if sku.Id != nil && *sku.Id > 0 {
						var productId string
						var itemCode string
						var itemTitle string
						var skuQuantity uint64
						var hasRefund uint64
						var imageUrl string
						var skuActualAmount float64
						var retailPrice float64
						var skuCode string
						var skuTitle string
						if sku.ProductId != nil && *sku.ProductId > 0 {
							productId = strconv.FormatUint(*sku.ProductId, 10)
						}
						if sku.Title != nil && len(*sku.Title) > 0 {
							itemTitle = *sku.Title
						}
						if sku.ActualAmount != nil && len(*sku.ActualAmount) > 0 {
							if f, err := moneyx.ParseAmountToFloat(*sku.ActualAmount); err == nil {
								skuActualAmount = f
							}
						}
						if sku.RetailPrice != nil && len(*sku.RetailPrice) > 0 {
							if f, err := moneyx.ParseAmountToFloat(*sku.RetailPrice); err == nil {
								retailPrice = f
							}
						}
						if sku.ProductCode != nil && len(*sku.ProductCode) > 0 {
							itemCode = *sku.ProductCode
						}
						if sku.SkuCode != nil && len(*sku.SkuCode) > 0 {
							skuCode = *sku.SkuCode
						}
						if sku.Sku != nil && len(*sku.Sku) > 0 {
							// *sku.Sku:  1-净含量-Net volume:0-50ml-
							skuTitle = strings.Split(strings.Split(*sku.Sku, ":")[1], "-")[1]
							// skuTitle: 50ml
						}
						if sku.Quantity != nil && *sku.Quantity > 0 {
							skuQuantity = uint64(*sku.Quantity)
						}
						if sku.RefundAmount != nil && len(*sku.RefundAmount) > 0 && *sku.RefundAmount != "0" {
							hasRefund = 1
						}
						if sku.ImageUrl != nil && len(*sku.ImageUrl) > 0 {
							imageUrl = *sku.ImageUrl
						}
						parcelSn := orderSn + "_" + strconv.FormatUint(*sku.Id, 10)
						orderItems = append(orderItems, map[string]any{
							"item_id":    productId,   // 商品编号  string
							"item_title": itemTitle,   // 商品标题  string
							"order_id":   parcelSn,    // 子交易单号  string
							"size":       skuQuantity, // 商品数量  integer
							// batch_date // 批次生产日期，格式 2023-11-01  string
							// batch_no // 批次信息  string
							// expired_date // 批次失效日期，格式 2023-12-01  string
							// extend // 扩展数据,Json形式<大客户定制字段,不用关注>  string
							// gx_payment // 供销payment  number
							// gx_price // 供销price  number
							// gx_price // 供销price  number
							"has_refund": hasRefund, // 明细是否退款  integer
							"image_url":  imageUrl,  // 商品图片地址  string
							"item_code":  itemCode,  // 外部商家编码，商家自己设定的编码, 尽量填写，ERP通过该编码区分商品  string
							// logistics_code  // 买家自选物流编码  string
							// logistics_name  // 买家所选物流昵称  string
							// order_attr  // 明细备注  string
							"payment":   skuActualAmount,                 // 商品实付（应收款）  number
							"price":     retailPrice,                     // 商品现价（商品单价）  number
							"sku_code":  skuCode,                         // 外部规格编码，商家自己设定的规格编码, 尽量填写，ERP通过该编码区分商品  string
							"sku_id":    strconv.FormatUint(*sku.Id, 10), // 规格编号  string
							"sku_title": skuTitle,                        // 规格标题  string
							// snapshot  // 商品交易快照地址  string
							"status":   status,  // 明细线上状态: 0：未创建订单；1：待付款；2：待发货；3：已完成；4：已关闭；5：已发货待确认；6：已签收；  integer
							"trade_id": orderSn, // 第三方交易号  string
						})
					}
				}
			}

			// 参考文档： https://open.hupun.com/api-doc/erp/b2c/trades/open
			trades = append(trades, map[string]any{
				"create_time":      *v.CreatedAt,                 // 交易创建时间，格式:yyyy-MM-dd HH:mm:ss（不能为空）  string <date-time>
				"modify_time":      updatedAt,                    // 交易最新修改时间，格式:yyyy-MM-dd HH:mm:ss  string<date-time>
				"orders":           orderItems,                   // 交易明细集  array[object]
				"receiver_address": detailedAddress,              // 收件人详细地址（不能为空）  string
				"receiver_name":    consignee,                    // 收件人姓名（不能为空）  string
				"shop_nick":        l.svcCtx.Config.Erp.ShopNick, // 在ERP中注册的卖家（店铺）昵称（不能为空）  string
				"status":           status,                       // 线上交易状态  integer
				"trade_id":         orderSn,                      // 第三方交易号  string
				// "back_img" // 身份证背面图片链接  string
				"buyer": buyer, // 买家  string
				// "buyer_email" // 买家邮件  string
				"buyer_message": remark, // 买家留言  string
				// "buyer_mobile":  mobile, // 订购人手机  string
				// "check_storage" // 校验仓库标识,当传入storeID时生效  integer
				// "clearance_code" // 清关单号  string
				// "clearance_discount":    discountAmount, // 优惠-非现金抵扣金额,清关使用  number
				// "clearance_item_amount": actualAmount, // 商品总金额,清关使用 number
				// "cpf_no" // 个人税号  string
				// "currency_code" // 金额币种  string
				// "delivery_code" // 外贸承运商编码  string
				"discount_fee": discountAmount, // 优惠金额 (总优惠)  number
				// "encrypt_address" // 收件人地址密文信息<大客户定制字段,不用关注>  string
				// "encrypt_consignee" // 收件人密文信息<大客户定制字段,不用关注>  string
				// "encrypt_consignee_phone" // 收件人手机号密文信息<大客户定制字段,不用关注>  string
				// "encrypt_flag" // 加密标识<大客户定制字段,不用关注>  integer
				"end_time": endedAt, // 交易结束时间 ，结束后必填, 格式:yyyy-MM-dd HH:mm:ss  string<date-time>
				// "express_code" // 快递单号  string
				// "extend" // 扩展数据,Json形式<大客户定制字段,不用关注>  string
				// "face_img" // 身份证正面图片链接  string
				"has_refund": hasOrderRefund, // 退款退货标记：1：退款；0：未退款  integer
				// "identity_name" // 身份证上的名称  string
				// "identity_num" // 身份证号  string

				// "invoice" // 发票信息(抬头)  string
				// "invoice_address" // 发票地址  string
				// "invoice_bank" // 发票开户行  string
				// "invoice_bank_account" // 发票银行账号  string
				// "invoice_email" // 发票邮箱  string
				// "invoice_mobile" // 发票电话  string
				// "invoice_remark" // 发票备注  string
				// "invoice_tax" // 发票税号  string
				// "invoice_type" // 发票类型 1:普通发票,2:增值税专用发票  integer
				// "invoicing_type" // 开票形式  integer

				// "last_ship_time" // 预计发货时间  string<date-time>
				// "logistics_code" // 快递公司编码，用户自定义编码  string
				// "origin_source_code" // 订单来源平台编码<大客户定制字段,不用关注>  string
				// "origin_source_order_id" // 原始平台单号<大客户定制字段,不用关注>  string
				// "origin_source_shop_nick" // 原始店铺昵称<大客户定制字段,不用关注>  string
				// "package_name" // 集包地名称  string
				// "pay_declare_amount" // 欠款金额 (传入金额后变成欠款订单)  number
				"pay_no":   payNo,   // 支付交易号  string
				"pay_time": paidAt,  // 交易付款时间 ，付款后必填, 格式:yyyy-MM-dd HH:mm:ss  string<date-time>
				"pay_type": payType, // 支付类型  string
				"payment":  amount,  // 应收款 （总金额-优惠金额+邮费）  number
				// "pdf_url" // 面单链接  string
				// "pics" // 图片及备注,传了会覆盖原先图片,最大支持八张图片  array[object]
				"post_fee":      freight,       // 邮费  number
				"print_config":  orderTypeText, // 订单类型  string
				"receiver_area": district,      // 收件人区/县  string
				"receiver_city": city,          // 收件人市（不能为空）  string
				// "receiver_country" // 收件人国家  string
				"receiver_mobile": mobile, // 收件人手机（不能为空）  string
				// "receiver_phone" // 收件人电话（手机和电话两者必填一处）  string
				"receiver_province": province,   // 收件人省（不能为空）  string
				"receiver_zip":      postalCode, // 收件人邮编  string
				// "route_code" // 三段码  string
				// "sales_mobile" // 业务员手机号-对应万里牛系统的业务员  string
				"seller_memo": sellerMemo, // 卖家备注  string
				// "service_fee" // 服务费  number
				// "shipping_time" // 交易发货时间 ，发货后必填, 格式:yyyy-MM-dd HH:mm:ss  string<date-time>
				"shipping_time": shippedAt, // 交易发货时间 ，发货后必填, 格式:yyyy-MM-dd HH:mm:ss  string<date-time>
				// "shipping_type" // 发货类型:1：EMS；2：平邮；0：快递；9：卖家承担运费；11：虚拟物品；121：自提；122：商家自送  integer
				// "store_id" // 门店ID  string
				"total_fee": actualAmount, // 总金额 (商品金额总数，不含邮费)  number
				// "trade_type" // 订单类型 1:一口价；5：货到付款；7：预约  integer
				"trade_type": 1,
			})
		}

		logx.Infof("PushOrderToErp getOrderMap trades: %+v ", trades)
		//[map[buyer:ed.蔡 buyer_message: create_time:2025-05-29 17:36:59 discount_fee:0 end_time: has_refund:1 modify_time:2025-05-29 18:07:00 orders:[map[has_refund:1 image_url:https://static.scentrobe.com/uploads/202307/77f99fd69e2b459a48dab6af2c02a29c.jpg item_code: item_id:7 item_title:神话女士 payment:0 price:8 size:1 sku_code:669632558 sku_id:93 sku_title:1ml status:0 trade_id:O20250529173658539827001]] pay_no:PMT20250529173658539827001 pay_time: pay_type:微信支付 payment:0.02 post_fee:10 print_config:实物订单 receiver_address:凤舞路30(北辰三角洲地铁站3号口步行280米) 开福城投大厦 receiver_area:开福区 receiver_city:长沙市 receiver_mobile:18588998859 receiver_name:徐小姐 receiver_province:湖南省 receiver_zip: seller_memo: shipping_time: shop_nick:shop1820 status:0 total_fee:10.01 trade_id:O20250529173658539827001 trade_type:1]]

		if len(trades) > 0 {
			items, err := json.Marshal(trades)
			if err != nil {
				logx.Errorw("PushOrderToErp getOrderMap json.Marshal err", logx.Field("detail", err.Error()))
				return nil, err
			}

			return map[string]string{
				"trades": string(items),
			}, nil
		}
	}

	return nil, nil
}

func (l *PushOrderToErpLogic) pushOrderToErp(queryMap map[string]string) error {
	if queryMap != nil {
		// logx.Infof("pushOrderToErp queryMap : %+v ", queryMap)
		path := "/erp/b2c/trades/open"
		erpClient := erp.NewErp(l.svcCtx.Config.Erp.AppKey, l.svcCtx.Config.Erp.Secret, l.svcCtx.Config.Erp.Url, path)
		err := erpClient.GetSign(queryMap)
		if err != nil {
			logx.Errorw("pushOrderToErp GetSign err", logx.Field("detail", err.Error()))
			return err
		}

		resMap, err := erpClient.CallErpApi()
		if err != nil {
			logx.Errorw("pushOrderToErp CallErpApi err", logx.Field("detail", err.Error()))
			return err
		}

		logx.Infof("pushOrderToErp response : %+v ", resMap)
		// map[response:[\"O20250529173658539827001\"] success:true]
		if !resMap["success"].(bool) {
			return errors.New(resMap["error_msg"].(string))
		}

		res := resMap["response"].(string)
		// logx.Infof("pushOrderToErp response1 : %+v ", res)
		// [\"O20250529173658539827001\"]

		var resp []string
		if err = json.Unmarshal([]byte(res), &resp); err != nil {
			logx.Errorw("pushOrderToErp json.Unmarshal err:", logx.Field("detail", err.Error()))
			// json: cannot unmarshal array into Go value of type map[string]interface {}
			return err
		}

		logx.Infof("pushOrderToErp response : %+v ", resp)
	}
	return nil
}
